package gupao.concurrency.lock.utils;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class ThreadPoolService {

    public static class SampleFutureTask<V> extends FutureTask<V>{
        Object task;
        public SampleFutureTask(Callable<V> callable) {
            super(callable);
            this.task = callable;
        }

        public SampleFutureTask(Runnable runnable, V result) {
            super(runnable, result);
            this.task = runnable;
        }

        @Override
        public String toString() {
            return "SampleFutureTask{" +
                    "task=" + task +
                    '}';
        }
    }

    private final static ConcurrentHashMap<String, ThreadPoolExecutor> threadPoolMap = new ConcurrentHashMap<>();

    public static ThreadPoolExecutor getOrCreateThreadPoolExecutor(String bizName,
                                                                   int corePoolSizeForCreateNew,
                                                                   int maxPoolSizeForCreateNew,
                                                                   BlockingQueue<Runnable> taskQueueForCreateNew,
                                                                   boolean isThreadDaemon){
        return threadPoolMap.computeIfAbsent(bizName, k -> create(bizName, corePoolSizeForCreateNew,
                                                                    maxPoolSizeForCreateNew, taskQueueForCreateNew, isThreadDaemon)) ;
    }

    public static void shutdown(String bizName){
        ThreadPoolExecutor executor = threadPoolMap.get(bizName);
        if(executor != null){
            executor.shutdown();
            log.info("thread pool {} shutdown.", bizName);
        }
    }

    public static List<Runnable> shutdownNow(String bizName){
        ThreadPoolExecutor executor = threadPoolMap.get(bizName);
        if(executor != null){
            log.info("thread pool {} shutdown now.", bizName);
            return executor.shutdownNow();
        }
        return new ArrayList<>();
    }

    private static ThreadPoolExecutor create(String prefix, int corePoolSize, int maxPoolSize, BlockingQueue<Runnable> queue,boolean isThreadDaemon){
        return new ThreadPoolExecutor(corePoolSize, maxPoolSize, 60, TimeUnit.SECONDS, queue, new ThreadFactory() {
            final AtomicInteger idx = new AtomicInteger(0);
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName(prefix + "-" + idx.incrementAndGet());
                t.setDaemon(isThreadDaemon);
                t.setPriority(Thread.NORM_PRIORITY);
                return t;
            }
        }){
            @Override
            protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
                return new SampleFutureTask<>(runnable, value);
            }

            @Override
            protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
                return new SampleFutureTask<>(callable);
            }
        };
    }
}
